#include "file_system.h"


void FileSystem::listDir(const char* dirname)
{
  // Serial.printf("Listing directory: %s\n", dirname);

  File root = SD.open(dirname);
  if (!root)
  {
    client.write("Failed to open directory");
    return;
  }
  if (!root.isDirectory())
  {
    client.write("Not a directory");
    return;
  }
  File file = root.openNextFile();
  while (file)
  {
    if (file.isDirectory())
    {
      client.write("  DIR : ");
      client.write(file.name());
      client.write("\n");
    }
    else
    {
     client.write("  FILE: ");
     client.write(file.name());
     client.write("  SIZE: ");
     client.write(String(file.size()/1024).c_str());
     client.write("KB\n");
    }
    file = root.openNextFile();
  }
}

void FileSystem::createDir(const char* path)
{
  if (SD.mkdir(path))
  {
    client.write("Dir created successfully!\n");
  }
  else
  {
    client.write("mkdir failed\n");
  }
}

void FileSystem::removeDir(const char* path)
{
  File root = SD.open(path);
  if (root.isDirectory())
  {
    File file = root.openNextFile();
    while (file)
    {
      if (file.isDirectory())
        removeDir(file.name());
      else
        SD.remove(file.name());
      file = root.openNextFile();
    }
  }
  if (SD.rmdir(path))
    client.write((String(path) + " removed successfully!\n").c_str());
  else
    client.write("rmdir failed\n");
}

void FileSystem::deleteallFile(const char* path)
{
  File root = SD.open(path);
  if (root.isDirectory())
  {
    File file = root.openNextFile();
    while (file)
    {
      if (file.isDirectory())
        deleteFile(file.name());
      else
        SD.remove(file.name());
      file = root.openNextFile();
    }
  }
  else
  {
    client.write("rmfile failed\n");
  }
}

void FileSystem::readFile(const char* path)
{
  client.write(("Reading file: "+String(path)+"\n").c_str());

  File file = SD.open(path);
  if (!file)
  {
    client.write("Failed to open file for reading\n");
    return;
  }

  client.write("Read from file: ");
  while (file.available())
  {
    client.write(file.read());
  }
  file.close();
}

String FileSystem::readFileLine(const char* path, int num)
{
  client.write(("Reading file: "+String(path)+" line: "+String(num)+"\n").c_str());

  File file = SD.open(path);
  if (!file)
  {
    return ("Failed to open file for reading");
  }

  char* p = buf;
  while (file.available())
  {
    char c = file.read();
    if (c == '\n')
    {
      num--;
      if (num == 0)
      {
        *(p++) = '\0';
        String s(buf);
        s.trim();
        file.close();
        return s;
      }
    }
    else if (num == 1)
    {
      *(p++) = c;
    }
  }
  file.close();
  return  String("error parameter!");
}

void FileSystem::createFile(const char* path)
{
  File file = SD.open(path, FILE_WRITE);
  if(!file)
  {
    client.write("Failed to create file\n");
  }
  else{
    file.close();
  }
}

void FileSystem::renameFile(const char* path1, const char* path2)
{
 client.write(("Renaming file "+String(path1)+" to "+String(path2)+"\n").c_str());
  if (SD.rename(path1, path2))
  {
    client.write("File renamed\n");
  }
  else
  {
    client.write("Rename failed\n");
  }
}

void FileSystem::deleteFile(const char* path)
{
  client.write("Deleting file: ");
  client.write(path);
  client.write("\n");

  if (SD.remove(path))
  {
    client.write("File deleted successfully!\n");
  }
  else
  {
    client.write("Delete failed\n");
  }
}

void FileSystem::get_sd_message()
{
    uint8_t cardType = SD.cardType();

    if (cardType == CARD_NONE)
    {
    client.write("No SD card attached\n");
    return;
    }

    client.write("SD Card Type: ");
    if (cardType == CARD_MMC)
    {
    client.write("MMC\n");
    }
    else if (cardType == CARD_SD)
    {
    client.write("SDSC\n");
    }
    else if (cardType == CARD_SDHC)
    {
    client.write("SDHC\n");
    }
    else
    {
    client.write("UNKNOWN\n");
    }
    int cardSize = SD.cardSize() / (1024 * 1024);
    client.write(("SD Card Size: "+String(cardSize)+"MB\n").c_str());
    int cardUsedSize = SD.usedBytes() / (1024 * 1024);
    client.write(("SD Card Used Size: "+String(cardUsedSize)+"MB\n").c_str());
}

void FileSystem::command_base(String cmd)
{
    // return;
    int blank_pos;
    blank_pos = cmd.indexOf(' ');//检测字符串中的逗号
    String cmd_dict, cmd_var;
    bool cmd_error=false;
    if (cmd=="ls")
    {
      if (cur_path=="")
        listDir("/");
      else
        listDir(cur_path.c_str());  
    }
    else if (cmd == "df")
    {
      get_sd_message();
    }
    else if(blank_pos != -1)
    {
        cmd_dict = cmd.substring(0, blank_pos);
        cmd_var = cmd.substring(blank_pos+1, cmd.length());
        if(!cmd_var.startsWith("/")&&!cmd_var.startsWith(".."))
            cmd_var = cur_path + "/" +cmd_var;
        else if(cmd_var.startsWith(".."))
        {
              int pos = cur_path.lastIndexOf('/');
              cmd_var = cmd_var.substring(2, -1);
              cmd_var = cur_path.substring(0, pos) + cmd_var;
              if (cmd_var.length()==0)
                cmd_var="/";
        }
        if (cmd_dict == "cd")
        {
          if (!SD.open(cmd_var) || !SD.open(cmd_var).isDirectory())
            client.write("Folder not exists!\n");
          else
          {
              if (cmd_var=="/")
                cur_path = "";
              else
                cur_path = cmd_var;
          }
        }
        else if (cmd_dict == "mkdir")
          createDir(cmd_var.c_str());
        else if (cmd_dict == "rmdir")
          removeDir(cmd_var.c_str());
        else if (cmd_dict == "mkfile")
          createFile(cmd_var.c_str());
        else if (cmd_dict == "rmfile")
        {
          Serial.println(cmd_var.substring(0, cmd_var.length()-2));
          if (cmd_var.endsWith("*"))
          {
            if (cur_path=="")
              cmd_var = "/";
            else
              cmd_var = cmd_var.substring(0, cmd_var.length()-2);
            deleteallFile(cmd_var.c_str());
          } 
          else
            deleteFile(cmd_var.c_str());
        }
        else
          cmd_error=true;    
    }
    else
    {
     cmd_error=true;
    }
    if (cmd_error)
    {
       client.write("command not found!\n");
    }
}

void FileSystem::recv_file(String cmd)
{
  String cmd_dict, cmd_dst;
  uint8_t *buf_rev = new uint8_t[64*1024];
  int r;
  int blank_pos;
  String comdata = "";
  int byte_cnt = 0;
  blank_pos = cmd.indexOf(' ');
  cmd_dict = cmd.substring(0, blank_pos);
  cmd = cmd.substring(blank_pos+1, cmd.length());
  blank_pos = cmd.indexOf(' ');
  cmd_dst = cmd.substring(0, blank_pos);
  if(!cmd_dst.startsWith("/"))
  {
    cmd_dst = cur_path + "/" +cmd_dst;
  }
  byte_cnt = cmd.substring(blank_pos+1, cmd.length()).toInt();;
  
  if (cmd_dict=="send_file")
  {
    client.write("ready");
    client.write_P("\0", 1);
  }
  else{
    client.write("error");
    client.write_P("\0", 1);
    return ;
  }
  // delay(100);
  // buf = new uint8_t[byte_cnt];
  File f = SD.open(cmd_dst.c_str(), FILE_WRITE);
  for(int i=0;i<byte_cnt;)
    if (client.available())
    {
      r = client.read(buf_rev, 1024*64);
      f.write(buf_rev, r);
      i+=r;
    }
    while(client.available())
    {
        client.read();
    }
  f.close();
  f = SD.open(cmd_dst.c_str(), FILE_READ);
  client.write(("Received size: " + String(f.size())+"\n").c_str());
  client.write("successfully receiving!");
  client.write_P("\0", 1);
  f.close();
  delete[] buf_rev;
}